﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Security;
using System.Security.Cryptography;
using System.IO;

namespace He.Common
{
    /// <summary>
    /// 加密解密辅助类
    /// </summary>
    public class CryptoHelper
    {

        #region MD5消息摘要
        /// <summary>
        /// MD5加密的默认附加字符串
        /// </summary>
        private const string MD5Key = "ShowMeTheMoney";

        /// <summary>
        /// 使用MD5加密
        /// </summary>
        /// <param name="plaintext">明文</param>
        /// <returns>密文</returns>
        public static string MD5(string plaintext)
        {
            return MD5(plaintext, MD5Key);
        }

        /// <summary>
        /// 使用MD5加密
        /// </summary>
        /// <param name="plaintext">明文</param>
        /// <param name="addKey">附加字符串</param>
        /// <returns>密文</returns>
        public static string MD5(string plaintext, string addKey)
        {
            string s = StringHelper.RingShiftLeft(plaintext, 3) + addKey;   //将明文做移位处理并添加附加串
            s = FormsAuthentication.HashPasswordForStoringInConfigFile(s, "MD5");
            s = StringHelper.RingShiftRight(s, 5);          //对MD5摘要后的字符串做移位处理
            return s;
        }
        #endregion

        #region SHA1加密
        /// <summary>
        /// SHA1加密，等效于 PHP 的 SHA1() 代码
        /// </summary>
        /// <param name="source">被加密的字符串</param>
        /// <returns>加密后的字符串</returns>
        public static string SHA1(string source)
        {
            byte[] temp1 = Encoding.UTF8.GetBytes(source);

            SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
            byte[] temp2 = sha.ComputeHash(temp1);
            sha.Clear();

            //注意，不能用这个
            //string output = Convert.ToBase64String(temp2); 

            string output = BitConverter.ToString(temp2);
            output = output.Replace("-", string.Empty);
            output = output.ToLower();
            return output;
        }
        #endregion

        #region DES 加密解密
        /// <summary>
        /// DES默认密钥
        /// </summary>
        private const string DES_KEY = "䦆頿䱷顠";

        #region 加密
        /// <summary>
        /// DES加密
        /// </summary>
        /// <param name="data">待加密字符串</param>
        /// <param name="key">密钥</param>
        /// <returns>加密后字符串</returns>
        public static string DESEncrypt(string data, string key)
        {
            //有效验证
            //if (key.Length != 4)
            //    throw new ArgumentOutOfRangeException("key", "参数密钥的长度必须是4，传入的密钥长度不合法");

            //定义DES加密服务提供类
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            //加密字符串转换为byte数组
            byte[] inputByte = null;
            byte[] deskey = new byte[8];
            if (DES_KEY != key)
            {
                inputByte = UnicodeEncoding.Default.GetBytes(data);
                deskey = UnicodeEncoding.Default.GetBytes(key);
            }
            else
            {
                inputByte = UnicodeEncoding.Unicode.GetBytes(data);
                deskey = UnicodeEncoding.Unicode.GetBytes(key);
            }
            //加密密匙转化为byte数组

            des.Key = deskey;
            des.IV = deskey;
            //创建其支持存储区为内存的流
            MemoryStream ms = new MemoryStream();
            //定义将数据流链接到加密转换的流
            CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);

            cs.Write(inputByte, 0, inputByte.Length);
            cs.FlushFinalBlock();
            StringBuilder ret = new StringBuilder();
            foreach (byte b in ms.ToArray())
            {
                //向可变字符串追加转换成十六进制数字符串的加密后byte数组。
                ret.AppendFormat("{0:X2}", b);
            }
            return ret.ToString();
        }

        /// <summary>
        /// DES加密
        /// </summary>
        /// <param name="data">待加密字符串</param>
        /// <returns>加密后字符串</returns>
        public static string DESEncrypt(string data)
        {
            return DESEncrypt(data, DES_KEY);
        }
        #endregion

        #region 解密
        /// <summary>
        /// DES解密
        /// </summary>
        /// <param name="data">被解密的加密字符串</param>
        /// <param name="key">密钥</param>
        /// <returns>解密后字符串</returns>
        public static string DESDecrypt(string data, string key)
        {
            //有效验证
            //if (key.Length != 4)
            //    throw new ArgumentOutOfRangeException("key", "参数密钥的长度必须是4，传入的密钥长度不合法");

            //定义DES加密解密服务提供类
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            //加密密匙转化为byte数组
            byte[] deskey = new byte[8];
            if (DES_KEY != key)
            {
                deskey = UnicodeEncoding.Default.GetBytes(key);
            }
            else
            {
                deskey = UnicodeEncoding.Unicode.GetBytes(key);
            }
            des.Key = deskey;
            des.IV = deskey;
            //将被解密的字符串每两个字符以十六进制解析为byte类型，组成byte数组
            int length = (data.Length / 2);
            byte[] inputByte = new byte[length];
            for (int index = 0; index < length; index++)
            {
                string substring = data.Substring(index * 2, 2);
                inputByte[index] = Convert.ToByte(substring, 16);
            }
            //创建其支持存储区为内存的流
            MemoryStream ms = new MemoryStream();
            //定义将数据流链接到加密转换的流
            CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
            cs.Write(inputByte, 0, inputByte.Length);
            cs.FlushFinalBlock();
            if (DES_KEY != key)
            {
                return UnicodeEncoding.Default.GetString((ms.ToArray()));
            }
            else
            {
                return UnicodeEncoding.Unicode.GetString((ms.ToArray()));
            }
        }

        /// <summary>
        /// DES解密
        /// </summary>
        /// <param name="data">被解密的加密字符串</param>
        /// <returns>解密后字符串</returns>
        public static string DESDecrypt(string data)
        {
            return DESDecrypt(data, DES_KEY);
        }
        #endregion

        #endregion

        #region 三重DES

        #endregion

        #region AES

        #endregion


    }
}
